package me.yidasanqian.crowdfunding.app;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import me.yidasanqian.crowdfunding.domain.Comment;
import me.yidasanqian.crowdfunding.domain.CrowdFund;
import me.yidasanqian.crowdfunding.domain.Media;
import me.yidasanqian.crowdfunding.domain.Progress;
import me.yidasanqian.crowdfunding.service.ICommentService;
import me.yidasanqian.crowdfunding.service.ICrowdFundingService;
import me.yidasanqian.crowdfunding.service.IMediaService;
import me.yidasanqian.crowdfunding.vo.CommentVo;
import me.yidasanqian.crowdfunding.vo.ResultModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

/**
 * @author Linyu Chen
 */
@RestController
@RequestMapping("api/v1/crowd_funding")
public class CrowdFundingApi {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Resource
    private ICrowdFundingService crowdFundingService;

    @Resource
    private IMediaService mediaService;

    @Resource
    private ICommentService commentService;

    @Value("${spring.http.multipart.location}")
    private String filePath;

    @RequestMapping(value = "add", method = RequestMethod.POST)
    public Object add(CrowdFund crowdFund,
                      @RequestParam("cover") MultipartFile cover,
                      @RequestParam(value = "video", required = false) MultipartFile video,
                      @RequestParam("goalFund") BigDecimal goalFund,
                      @RequestParam("needDay") Integer needDay,
                      HttpServletRequest request) {

        // todo 视频参数

        if (cover.isEmpty()) {
            return ResultModel.fail(1007, "上传的文件不能为空");
        }
        String imageType = "image/";
        String videoType = "video/";
        String servletPath = request.getScheme() + "://" + request.getServerName() +
                ":" + request.getServerPort();
        // 判断文件类型
        if (!cover.getContentType().contains(imageType)) {
            return ResultModel.fail(1012, "不允许的媒体文件类型");
        }

        Date time = new Date();

        String imageUrl = transferFile(cover, imageType);
        String videoUrl = transferFile(video, videoType);
        Media imgMedia = saveMedia(crowdFund.getTitle(), imageUrl, 0);
        Media videoMedia = saveMedia(crowdFund.getTitle(), videoUrl, 1);
        if (imgMedia != null) {
            crowdFund.setCoverId(imgMedia.getId());
        }
        if (videoMedia != null) {
            crowdFund.setVideoId(videoMedia.getId());
        }

        Progress progress = new Progress();
        progress.setGoalFund(goalFund);
        progress.setNeedDay(needDay);
        //progress.setCreateTime(time);
        crowdFundingService.saveProgress(progress);

        crowdFund.setProgress(progress);
        //crowdFund.setCreatetime(time);
        // todo 审核状态
        crowdFund.setStatus(1);
        crowdFund.setFollowCount(0);
        crowdFundingService.save(crowdFund);
        return ResultModel.success();
    }

    private Media saveMedia(String title, String mediaUrl, int mediaType) {
        Media media = null;
        if (!StringUtils.isEmpty(mediaUrl)) {
            media = new Media();
            media.setUrl(mediaUrl);
            media.setMediaType(mediaType);
            media.setTitle(title);
            mediaService.save(media);
        }
        return media;
    }

    @Deprecated
    private String transferFile(String servletPath, MultipartFile file, String contentType) {
        String fileUrl = null;
        if (file != null) {
            // 获取文件名
            String filename = file.getOriginalFilename();
            // 获取文件的后缀名
            String suffixName = filename.substring(filename.lastIndexOf("."));
            log.info("上传的后缀名为：" + suffixName);

            // 解决中文问题，liunx下中文路径，图片显示问题
            filename = UUID.randomUUID() + suffixName;
            String fileUri = contentType + filename;
            String pathName = filePath + fileUri;
            File dest = new File(pathName);
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                file.transferTo(dest);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            fileUrl = servletPath + "/" + fileUri;
        }

        return fileUrl;
    }

    private String transferFile(MultipartFile file, String contentType) {
        String fileUrl = null;
        if (file != null) {
            // 获取文件名
            String filename = file.getOriginalFilename();
            // 获取文件的后缀名
            String suffixName = filename.substring(filename.lastIndexOf("."));
            log.info("上传的后缀名为：" + suffixName);

            // 解决中文问题，liunx下中文路径，图片显示问题
            filename = UUID.randomUUID() + suffixName;
            String fileUri = contentType + filename;
            String pathName = filePath + fileUri;
            File dest = new File(pathName);
            // 检测是否存在目录
            if (!dest.getParentFile().exists()) {
                dest.getParentFile().mkdirs();
            }
            try {
                file.transferTo(dest);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }

            fileUrl = fileUri;
        }

        return fileUrl;
    }

    @RequestMapping(value = "list", method = RequestMethod.GET)
    public Object listCrowdFund(@RequestParam("pn") Integer pn,
                                @RequestParam("ps") Integer ps) {
        Page<CrowdFund> page = PageHelper.startPage(pn, ps);
        List<CrowdFund> crowdFundList = crowdFundingService.listCrowdFund();
        long total = page.getTotal();
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put("crowdFundList", crowdFundList);
        map.put("total", total);
        return ResultModel.success(map);
    }

    @RequestMapping(value = "getByFundId", method = RequestMethod.GET)
    public Object getByFundId(@RequestParam("fundId") Long fundId) {
        CrowdFund crowdFund = crowdFundingService.getCrowdFund(fundId);
        return ResultModel.success(crowdFund);
    }

    @RequestMapping(value = "listByUserId", method = RequestMethod.GET)
    public Object listByUserId(@RequestParam("userId") Long userId,
                               @RequestParam("pn") Integer pn,
                               @RequestParam("ps") Integer ps) {
        Page<CrowdFund> page = PageHelper.startPage(pn, ps);
        List<CrowdFund> crowdFundList = crowdFundingService.listByUserId(userId);
        long total = page.getTotal();
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put("crowdFundList", crowdFundList);
        map.put("total", total);
        return ResultModel.success(map);
    }

    @RequestMapping(value = "getByUserIdAndFundId", method = RequestMethod.GET)
    public Object getByUserIdAndFundId(@RequestParam("userId") Long userId,
                                       @RequestParam("fundId") Long fundId) {
        CrowdFund crowdFund = crowdFundingService.getByUserIdAndFundId(userId, fundId);
        return ResultModel.success(crowdFund);
    }

    @RequestMapping(value = "getMedia", method = RequestMethod.GET)
    public Object getFilePathName(@RequestParam("mediaId") Long mediaId) {
        Media media = mediaService.selectByPrimaryKey(mediaId);
        return ResultModel.success(media);
    }

   /* @RequestMapping(value = "delete", method = RequestMethod.POST)
    public Object delete(@RequestParam("crowdFundId")Integer crowdFundId) {
        crowdFundingService.deleteById(crowdFundId);
        return ResultModel.success();
    }

    @RequestMapping(value = "update", method = RequestMethod.POST)
    public Object update(CrowdFund crowdFund,@RequestParam("cover")MultipartFile cover,
                         @RequestParam(value = "video", required = false)MultipartFile video,
                         HttpServletRequest request) {
        crowdFundingService.update(crowdFund);
        return ResultModel.success();
    }*/

    @RequestMapping(value = "follow", method = RequestMethod.POST)
    public Object followCrowdFunding(@RequestParam("userId") Long userId,
                                     @RequestParam("fundId") Long fundId) {
        CrowdFund crowdFund = crowdFundingService.getCrowdFund(fundId);
        String follow = crowdFund.getFollow();
        Integer followCount = crowdFund.getFollowCount();
        if (StringUtils.isEmpty(follow)) {
            follow = "";
            followCount = 0;
        } else {
            int[] userIds = stringArrToIntArr(follow);
            for (int i = 0; i < userIds.length; i++) {
                if (userIds[i] == userId) {
                    return ResultModel.fail(1015, "您已关注过该众筹项目");
                }
            }
        }
        follow += userId;
        follow += "|";
        crowdFund.setFollow(follow);
        followCount++;
        crowdFund.setFollowCount(followCount);
        crowdFundingService.update(crowdFund);
        return ResultModel.success();
    }

    @RequestMapping(value = "cancelFollow", method = RequestMethod.POST)
    public Object cancelFollowCrowdFunding(@RequestParam("userId") Long userId,
                                           @RequestParam("fundId") Long fundId) {
        CrowdFund crowdFund = crowdFundingService.getCrowdFund(fundId);
        String follow = crowdFund.getFollow();
        Integer followCount = crowdFund.getFollowCount();
        if (StringUtils.isEmpty(follow)) {
            return ResultModel.fail(6000, "非法操作");
        } else {
            String[] followArr = follow.split("\\|");
            for (int i = 0; i < followArr.length; i++) {
                String f = followArr[i];
                if (!StringUtils.isEmpty(f) && f.equals(String.valueOf(userId))) {
                    follow = handlerUserIdsString(userId, f);
                    break;
                }
            }
        }
        followCount--;
        if (followCount < 0) {
            followCount = 0;
        }
        crowdFund.setFollowCount(followCount);
        crowdFund.setFollow(follow);
        crowdFundingService.update(crowdFund);
        return ResultModel.success();
    }

    @RequestMapping(value = "isFollowCrowdFunding", method = RequestMethod.GET)
    public Object isFollowCrowdFunding(@RequestParam("userId") Long userId,
                                       @RequestParam("fundId") Long fundId) {
        CrowdFund crowdFund = crowdFundingService.getCrowdFund(fundId);
        String follow = crowdFund.getFollow();
        Map<String, Boolean> map = new HashMap<String, Boolean>();
        if (StringUtils.isEmpty(follow)) {
            map.put("isFollowCrowdFunding", false);
        } else {
            String[] followArr = follow.split("\\|");
            for (int i = 0; i < followArr.length; i++) {
                String f = followArr[i];
                if (!StringUtils.isEmpty(f) && f.equals(String.valueOf(userId))) {
                    map.put("isFollowCrowdFunding", true);
                    break;
                }
            }
        }

        return ResultModel.success(map);
    }

    private String handlerUserIdsString(Long userId, String dbString) {
        String[] followArr = dbString.split("\\|");
        for (int i = 0; i < followArr.length; i++) {
            String f = followArr[i];
            if (!StringUtils.isEmpty(f) && f.equals(String.valueOf(userId))) {
                followArr[i] = "";
                break;
            }
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < followArr.length; i++) {
            String f = followArr[i];
            if (!StringUtils.isEmpty(f)) {
                sb.append(f);
                sb.append("|");
            }
        }
        return sb.toString();
    }

    private int[] stringArrToIntArr(String str) {
        String[] sArr = str.split("\\|");
        int[] iArr = new int[sArr.length];
        for (int i = 0; i < sArr.length; i++) {
            iArr[i] = Integer.parseInt(sArr[i]);
        }
        return iArr;
    }

    // 项目评论
    @RequestMapping(value = "commentCrowdFunding", method = RequestMethod.POST)
    public Object commentCrowdFunding(Comment comment,
                                      @RequestParam(value = "file", required = false) MultipartFile part,
                                      HttpServletRequest request) {
        if (part != null) {
            String imageType = "image/";
            String servletPath = request.getScheme() + "://" + request.getServerName() +
                    ":" + request.getServerPort();
            // 判断文件类型
            if (!part.getContentType().contains(imageType)) {
                return ResultModel.fail(1012, "不允许的媒体文件类型");
            }
            String imageUrl = transferFile(part, imageType);
            Media imgMedia = saveMedia(comment.getContent(), imageUrl, 0);
            if (imgMedia != null) {
                comment.setMediaId(imgMedia.getId());
            }
        }

        Date time = new Date();
        //comment.setCreatetime(time);
        commentService.save(comment);
        return ResultModel.success();
    }

    @RequestMapping(value = "listCommentsByFundId", method = RequestMethod.GET)
    public Object listCommentsByFundId(@RequestParam("fundId") Long fundId,
                                       @RequestParam("pn") Integer pn,
                                       @RequestParam("ps") Integer ps) {
        Page<CommentVo> page = PageHelper.startPage(pn, ps);
        List<CommentVo> commentList = commentService.listCommentsByFundId(fundId);
        int total = (int) page.getTotal();
        Map<String, Object> data = new HashMap<String, Object>();
        data.put("commentList", commentList);
        data.put("total", total);
        return ResultModel.success(data);
    }
}
